\bibliographystyle{gbt7714-2005}

\chapter{如何学习编程}

\epigraphhead[60]{\epigraph{You can code. They cannot. That is pretty damn cool.}{\textit{Zed A. Shaw《Learn Python The Hard Way》}}}

如今编程成为了一个越来越重要的能力：作为设计师，懂一些编程可能会帮你更好地理解自己的工作内容；作为创业者，技术创始人的身份则会让你的很多工作显得更容易；作为研究者，学会编程能让你按照自己的意图获取数据和处理数据。无论哪个行业，都面临着如何同互联网相融合的机遇和挑战。具备一定的编程能力，无疑会提高在互联网时代的竞争实力。

刚开始学习编程的新手，常面临这样的问题：面对各种学习资料，不知道从哪里开始；好不容易入门后，发现需要学习的内容越来越多、越来越难，陡峭的学习曲线使人望而却步；虽然具有一定的基础知识，但是不知道如何进行一个真正的项目。

幸运的是，我们现在处于互联网蓬勃发展的时代，初学者面临的这些问题，已经有诸多的解决方案，在这一章节中，我们一起了解前人们的经验和教训，从而提高学习效率。

\section{调整心态}

首先要明确一点，编程不是一件轻轻松松就能学会的技能。虽然能在书店中看到大量类似
《21天学通XXX》的书籍，但一旦你开始学习的时候，就会有这样的体验：所谓的捷径是不存在的，尤其是在编程领域，只要有一处错误，有一处你没有真正掌握的知识点，你就会卡在哪里，只有排除错误后，你才能继续下一个任务。一句话：学习编程意味着你将需要投入大量的时间和精力。

在学习编程的过程中，一些人容易放弃的原因主要有三点：一是没有目标，不知道掌握了编程技能后能解决什么具体问题。二是乏味，在学习编程语言的基础知识（如语法规则、编程模式）时提不起兴趣。三是觉得难，有些知识点的确不是一下就能理解，尝试后知难而退。

如何解决这些学习过程中遇到的困惑呢？根据我个人的经验和别人的总结，提出如下建议：

\subsection{明确目标}

在你学习编程之前思考一下你的目标，你想要用这门语言写什么？网站？游戏？手机APP？还是想自动完成一些乏味重复的任务？亦或你只是想找个好工作。当然，所有的这些都是有价值的目标，这些目标都是你学习的驱动力，没有驱动力，很有可能在略显枯燥的漫长学习之旅中半途而废。

行为科学家认为，人的驱动力分为三种：第一驱动力是生物性需求，即对食物、性欲等等的需求；第二驱动力则来自外在动机，做出特定行为时环境会带来的奖励或惩罚；第三驱动力来自于内在动机，我们有“发现新奇事物、进行挑战、拓展并施展才能以及探索和学习的内在倾向”。\cite{丹尼尔•平克，2012}第三种驱动力比另外两种更脆弱，它只有在合适的环境中才能存在。人们发现，以乐为本的内在动机，也就是\textbf{感受到自己的创造力是最强大的动机}，才是真正能驱动人们进行自我管理、不断前进的动力。Linux操作系统的主创人员——大神李纳斯·特沃兹在自传《乐者为王》中也谈到类似的观点：很多顶尖的程序员写程序的目的，并不是为了赚钱或者得到公众的奉承，而是觉得写程序本身很有趣。\cite{李纳斯·托沃兹，2001}

\subsection{保持兴趣}

赫伯特·亚历山大·西蒙\footnote{赫伯特·亚历山大·西蒙（英语：Herbert Alexander Simon，1916年6月15日－2001年2月9日），美国著名学者，计算机科学家和心理学家，研究领域涉及认知心理学、计算机科学、公共行政、经济学、管理学和科学哲学等多个方向。1975年图灵奖得主，1978年，获得诺贝尔经济学奖。}认为，人是有限理性的动物，体现在学习中，就是情境理性。即“在哪里用，就在哪里学”，人的学习受到情景制约或者促进。你要学习的东西将实际应用在什么情境中，那么你就应该在什么样的情境中学习这些东西。比如，你要学习讨价还价的技巧，就应该在实际的销售场合学习，因为这一技巧最终是用在销售场合的。

了解到这些行为科学的研究成果后，我们应该将编程和自己或者他人的实际需求结合起来进行学习和实践，也就是说，我们应该利用计算机解决实际的问题，这样才能保持足够的驱动力。当然，人在不同阶段的需求会有变化。比如我刚毕业时，刚接触互联网，觉得很神奇，就利用业余时间建立了一个班级网站，方便同学之间联系。后来，在复习考研的过程中，发现很多背单词软件都满足不了自己的需求，又在复习的间隙，写了一个背单词的工具。

总之，编程是连接理论与实践的纽带，是计算机科学与计算机应用技术相交融的领域。正确的编程学习方法应该是：通过自顶而下的探索与项目实践，获得编程直觉与推动力；从自底向上的打基础过程中，获得最重要的通用方法并巩固编程思想的理解。

\section{如何学习}

\subsection{快速迭代}

迭代是一个重复反馈过程的活动，每一次迭代的结果都会作为下一次迭代的初始值，从而不断逼近目标或结果。迭代的实质思想是每次循环不求完美，但求不断发现新问题，迅速求解，获取和积累新知识。具体到编程学习中，就是先快速了解一门编程语言的基本语法，之后就开始用这门语言解决问题，做出一个能用的版本，然后再不断优化。

尽快用学习的编程工具作出实际项目，还有个好处，那就是能在学习的过程中，不断感受到自己的创造力，按照之前提到的理论，这种内在动机，也就是因一件事很有趣、很有挑战性、很令人着迷而去做的驱动力，对于从事创造性工作的人（艺术家、科学家、发明家和在校学生等等）至关重要。

\subsection{内化输出}

在学习的过程中，做好笔记。对不太熟悉的知识点，结合项目经验，简单总结后发布在博客或者Github、Oschina等等版本管理站点上。当知识点能形成知识网络时，利用思维导图工具将知识点之间的逻辑关系表述出来。这样做，一方面能在日积月累中熟悉知识，方便日后查询温习；另一方面通过内容的创作，能有效提高学习的成就感，进而增强学习兴趣，进入学习的正向循环。

做笔记的时候，最好不要粘贴、复制网络现成的资料，具体可参考理查德·费曼\footnote{理查德·费曼（1918年5月11日－1988年2月15日），美国物理学家。1965年诺贝尔物理奖得主。}提出的以下步骤：\cite{费曼，2005}

\begin{enumerate}
	\item 选择你想要学习理解的概念；
	\item 假设你正在给别人讲解这个概念，写出这个概念的解释。当你试着给别人讲解这个概念时，可促进对这个概念的深入理解，也能及时发现对这个概念的模糊之处；
	\item 如果你卡在某个地方，回头查阅资料重新理解概念，只到你能达到上一步的要求；
	\item 简化你的表述。使用你自己的语言，而不是资料上的原话，简洁清晰地表述概念。如果你的解释比较混乱，那就意味着你可能并没有真正理解这个概念。
\end{enumerate}

\subsection{善用网络}
与其它领域的学习不同，学习编程有着高质量的网络资源，从官方文档到各种教程，从入门级别的练手代码到行业顶尖人员的作品，甚至开发工作中常见错误的解决办法，都可以从网络中获取。互联网本身就是一个友善的集体智慧创作群体的成果。我们应利用互联网，积极参与人类智慧的集体进化，这是最简单的让自己变得更智慧的方法。

\begin{enumerate}
	\item 在线教学网站。网络上有许多高质量的教学网站，如\href{http://www.imooc.com}{慕课网}、\href{http://www.code.org}{Code.org}等等，这些网站积累了大量优质教学资源。
	\item 官方网站。不管何种语言或者框架、库之类，其官方网站应该是学习者解决疑惑的首选；
	\item 专业问答网站。遇到问题时，去\href{http://segmentfault.com/}{SegmentFault.com}、\href{http://StackOverflow.com}{Stack Overflow}等专业编程问答网站查找或者提问；
	\item 代码托管网站。在开始项目前，最好到\href{http://github.com}{Github}等代码托管网站查看有无相近的项目。
	\item 利用Google等搜索引擎。
\end{enumerate}

最后，请同学们喝了这碗鸡汤：\href{http://v.youku.com/v_show/id_XNTIzNzE2NzQ4.html}{大多数学校不会教的东西}，以便精神饱满地继续学习。

本章节的写作，受到知乎用户萧井陌《编程入门指南》\cite{萧井陌，2015}的启发，在此致谢。

\bibliography{../bib/yangjh}
